package com.scene
{
	import com.game.events.GameEvent;
	import com.game.events.GameEventDispatcher;
	import com.game.events.GameEventType;
	import com.update.Update;
	import com.update.interfaces.IUpdate;
	import com.utils.Print;
	
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.utils.getTimer;

	/**
	 * 观景管理
	 * @author yangyang
	 *
	 */
	public class SceneManager
	{
		/**
		 * 消息机制
		 */
		private var notify : GameEventDispatcher;

		private static var instance : SceneManager;

		/**
		 * 场景容器
		 */
		private var container : DisplayObjectContainer;

		/**
		 * 游戏时间
		 */
		private var runTime : int;

		/**
		 * 当前可更新时间
		 */
		private var intervalTime : int;

		/**
		 * 高,中,低 3个级别的更新队列
		 */
		private var highUpdatables : Array = [];

		private var middenUpdatables : Array = [];

		private var lowUpdatables : Array = [];

		/**
		 * 当前场景数据
		 */
		private var sceneClass : Class;

		private var currScene : Sprite;

		private var oldeScene : Sprite;

		public function SceneManager()
		{
		}

		public static function getInstance() : SceneManager
		{
			if (instance == null)
			{
				instance = new SceneManager();
			}
			return instance;
		}

		/**
		 * 必须初始化
		 * @param stage
		 *
		 */
		public function init(stage : DisplayObjectContainer) : void
		{
			this.container = stage;
			this.runTime = getTimer();
			notify = GameEventDispatcher.getInstance();
			stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
			notify.addEventListener(GameEventType.ADD_UPDATE, addUpdateHandler);
			notify.addEventListener(GameEventType.DEL_UPDATE, delUpdateHandler);
		}

		public function getCurScene() : Sprite
		{
			return currScene;
		}

		public function isScene(stateClass : Class) : Boolean
		{
			return currScene is stateClass;
		}

		/**
		 * 转换场景
		 * @param stateName
		 *
		 */
		public function changeScene(stateClass : Class, isShowAnimation : Boolean = true) : Sprite
		{
			if (stateClass == null)
			{
				Print.error("转换场景错误:", stateClass);
				return null;
			}

			if (sceneClass == stateClass)
			{
				return null;
			}
			sceneClass = stateClass;

			if (currScene)
			{
				//currScene.destroy();
				oldeScene = currScene;
			}

			currScene = new stateClass();

			if (currScene)
			{
				container.addChild(currScene);
			}

			return currScene;
		}

		/**
		 * 帧频更新
		 * @param evt
		 *
		 */
		public function onEnterFrame(evt : Event) : void
		{
			intervalTime = getTimer() - runTime;
			runTime = getTimer();
			update(intervalTime);
		}

		/**
		 * 更新队列
		 * @param value
		 *
		 */
		public function update(value : int) : void
		{
			var i : int;
			var len : int = highUpdatables.length;

			for (i = len - 1; i >= 0; i -= 1)
			{
				if (highUpdatables[i] == null)
					continue;

				if (!highUpdatables[i].checkUpdatable(value) || lowUpdatables[i].isDestroy)
					continue;
				highUpdatables[i].update(value);
			}
			len = middenUpdatables.length;

			for (i = len - 1; i >= 0; i -= 1)
			{
				if (middenUpdatables[i] == null)
					continue;

				if (!middenUpdatables[i].checkUpdatable(value) || lowUpdatables[i].isDestroy)
					continue;
				middenUpdatables[i].update(value);
			}
			len = lowUpdatables.length;

			for (i = len - 1; i >= 0; i -= 1)
			{
				if (lowUpdatables[i] == null)
					continue;

				if (!lowUpdatables[i].checkUpdatable(value) || lowUpdatables[i].isDestroy)
					continue;
				lowUpdatables[i].update(value);
			}

		}

		/**
		 * 添加更新列表
		 * @param update   更新对象
		 * @param level    更新的等级,0低级,1中级,2高级
		 * @param priority 优先级
		 *
		 */
		public function addUpdateHandler(evt : GameEvent) : void
		{
			var update : IUpdate = evt.body as IUpdate;
			var updatableArray : Array;

			if (update == null)
				return;

			switch (update.registerdLevel)
			{
				case Update.PRIORITY_HIGH:
					updatableArray = highUpdatables;
					break;
				case Update.PRIORITY_MIDDEN:
					updatableArray = middenUpdatables;
					break;
				case Update.PRIORITY_LOW:
					updatableArray = lowUpdatables;
					break;
			}

			if (updatableArray == null)
				return;
			var index : int = updatableArray.indexOf(update);

			if (index != -1)
				return;
			update.priority = update.priority;
			updatableArray.push(update);
			updatableArray.sortOn("priority", Array.NUMERIC | Array.DESCENDING);
		}

		public function delUpdateHandler(evt : GameEvent) : void
		{
			var update : IUpdate = evt.body as IUpdate;
			var updatableArray : Array;

			if (update == null)
				return;

			switch (update.registerdLevel)
			{
				case Update.PRIORITY_HIGH:
					updatableArray = highUpdatables;
					break;
				case Update.PRIORITY_MIDDEN:
					updatableArray = middenUpdatables;
					break;

				case Update.PRIORITY_LOW:
					updatableArray = lowUpdatables;
					break;
			}

			if (updatableArray == null)
				return;
			var index : int = updatableArray.indexOf(update);

			if (index == -1)
				return;
			updatableArray.splice(index, 1);
			return;
		}

	}
}